package com.frost500.integrationdemo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.frost500.integrationdemo.mapper.StorageMapper;
import com.frost500.integrationdemo.model.Storage;
import com.frost500.integrationdemo.service.StorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 */
@Slf4j
@Service
public class StorageServiceImpl implements StorageService {

    @Autowired
    private StorageMapper storageMapper;

    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Override
    public void deductUnlock(Long id) {
        log.info("未加锁=》开始扣减库存");
        try {
            Storage storage = storageMapper.selectById(id);
            log.info("当前库存数量为：" + storage.getNum());
            if (storage.getNum() > 0) {
                storageMapper.deduct(id, 1L);
                log.info("扣减库存成功");
            } else {
                log.info("库存不足,扣减库存失败！");
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("扣减库存失败，可能是库存不足！");
        }
    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Override
    public void deductLocked(Long id) {
        try {
            log.info("加锁=》开始扣减库存");
            Storage storage = storageMapper.selectById(id);
            log.info("当前库存数量为：" + storage.getNum());
            if (storage.getNum() > 0) {
                storageMapper.deduct(id, 1L);
                storage = storageMapper.selectById(id);
                log.info("扣减库存成功，扣减后库存数量：" + storage.getNum());
            } else {
                log.info("库存不足,扣减库存失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("扣减库存失败，可能是库存不足！");
        }
    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Override
    public void deductDistributeLocked(Long id) {
        log.info("分布式锁=》开始扣减库存");
        try {
            Storage storage = storageMapper.selectById(id);
            log.info("当前库存数量为：" + storage.getNum());
            if (storage.getNum() > 0) {
                storageMapper.deduct(id, 1L);
                log.info("扣减库存成功");
            } else {
                log.info("库存不足,扣减库存失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("扣减库存失败，可能是库存不足！");
        }
    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Override
    public void insertStorage() {
        Storage storage = new Storage();
        storage.setGoodsName(UUID.randomUUID().toString());
        storage.setNum(20L);
        QueryWrapper<Storage> wrapper = new QueryWrapper<Storage>();
        Integer integer = storageMapper.selectCount(wrapper);
        storage.setSeq(integer.toString());
        storageMapper.insert(storage);
    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Override
    public void insertStorageLocked() {
        try {
            Storage storage = new Storage();
            storage.setGoodsName(UUID.randomUUID().toString());
            storage.setNum(20L);
            QueryWrapper<Storage> wrapper = new QueryWrapper<Storage>();
            Integer integer = storageMapper.selectCount(wrapper);
            storage.setSeq(integer.toString());
            storageMapper.insert(storage);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Override
    public void insertStorageDistributeLocked() {
        try {
            Storage storage = new Storage();
            storage.setGoodsName(UUID.randomUUID().toString());
            storage.setNum(20L);
            QueryWrapper<Storage> wrapper = new QueryWrapper<Storage>();
            Integer integer = storageMapper.selectCount(wrapper);
            storage.setSeq(integer.toString());
            storageMapper.insert(storage);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public List<Storage> getAll() {
        return storageMapper.selectList(null);
    }
}
